package com.becca.cake.service.orders.impl;

import java.awt.geom.Point2D;
import java.awt.geom.Point2D.Double;
import java.io.File;
import java.text.MessageFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import com.becca.cake.core.common.BaiduMapRangeCache;
import com.becca.cake.core.constant.CommonConstants;
import com.becca.cake.core.excel.excelWriter.ExcelInfo;
import com.becca.cake.core.excel.excelWriter.impl.ExcelWriteHandle;
import com.becca.cake.core.exception.ServiceException;
import com.becca.cake.core.freemarker.FreeMarkerHelp;
import com.becca.cake.core.map.baidu.map.BaiduLatitudeHelp;
import com.becca.cake.core.map.baidu.map.PtInPolyHelp;
import com.becca.cake.core.qiniu.QiNiuGoodsPicTemplate;
import com.becca.cake.core.qiniu.bean.QiNiuResponse;
import com.becca.cake.core.sms.SMSHelper;
import com.becca.cake.core.sms.message.SmsConfirmOrder;
import com.becca.cake.core.sms.message.SmsCreateOrder;
import com.becca.cake.core.sms.message.SmsRefundOrder;
import com.becca.cake.core.sms.message.SmsSendedOrder;
import com.becca.cake.core.socket.SocketMessage;
import com.becca.cake.dao.coupon.CouponDAO;
import com.becca.cake.dao.fixing.FixingDAO;
import com.becca.cake.dao.order.OrderDAO;
import com.becca.cake.dao.statistics.StatisticDAO;
import com.becca.cake.dao.users.UserManagerDAO;
import com.becca.cake.model.address.BaiduRangeParamModel;
import com.becca.cake.model.coupon.CouponModel;
import com.becca.cake.model.goods.GoodsFixingModel;
import com.becca.cake.model.goods.GoodsModel;
import com.becca.cake.model.logistic.LogisticStatusModel;
import com.becca.cake.model.order.GoodOrderModel;
import com.becca.cake.model.order.OrderDetailsModel;
import com.becca.cake.model.order.OrderExcelModel;
import com.becca.cake.model.order.OrderModel;
import com.becca.cake.model.order.OrderRefundsModel;
import com.becca.cake.model.order.OrdersTodayModel;
import com.becca.cake.model.statistics.FusionChartsModel;
import com.becca.cake.model.statistics.OrderReportDateTimeModel;
import com.becca.cake.model.statistics.OrderReportGoodsModel;
import com.becca.cake.model.statistics.OrderReportModel;
import com.becca.cake.model.users.UserAddressModel;
import com.becca.cake.model.users.UserPaymentsModel;
import com.becca.cake.service.orders.IOrderService;
import com.becca.cake.util.DateUtils;
import com.becca.cake.util.JsonUtil;
import com.becca.cake.util.Tools;

/**
 * 订单管理Service实现类
 * @copyright  尊星(上海)信息科技有限公司
 * @author yellow
 * @date 2016年5月18日 下午3:33:24
 */
@Service("iOrderService")
public class orderServiceImpl implements IOrderService {
    private static final Logger logger = LoggerFactory.getLogger(orderServiceImpl.class);
    @Autowired
    public OrderDAO             orderDAO;

    @Autowired
    private StatisticDAO        statisticDAO;

    @Autowired
    private UserManagerDAO      userManagerDAO;

    @Autowired
    private FixingDAO           fixingDAO;

    @Autowired
    private CouponDAO           couponDAO;

    @Override
    public List<OrderModel> selectOrders(Map<String, Object> map) throws ServiceException {
        return this.orderDAO.selectOrders(map);
    }

    @Override
    public Long selectOrdersCount(Map<String, Object> map) throws ServiceException {
        return this.orderDAO.selectOrdersCount(map);
    }

    @Override
    @Transactional(rollbackFor = Exception.class, propagation = Propagation.REQUIRED)
    public void updateOrder(OrderModel orderModel) throws Exception {
        // 1.stmp 校验订单数据
        OrderModel.validUpdateOrder(orderModel);
        //校验配送日期是否在330天范围内
        Date deliveryDate = orderModel.getDeliveryDate();
        Date maxDeliveryDate = DateUtils.getSomeDayDate(30);
        if (deliveryDate.getTime() > maxDeliveryDate.getTime()) {
            throw new ServiceException("配送日期必须在30天以内!");
        }
        this.orderDAO.updateOrder(orderModel);
    }

    @Override
    public OrderModel findOrderById(Integer orderId) throws Exception {
        OrderModel.validOrderIdNull(orderId);
        return this.orderDAO.findOrderById(orderId);
    }

    @Override
    public List<OrderDetailsModel> selectDetailsByOrderId(Integer orderId) throws ServiceException {
        OrderModel.validOrderIdNull(orderId);
        return this.orderDAO.selectDetailsByOrderId(orderId);
    }

    @Override
    @Transactional(rollbackFor = Exception.class, propagation = Propagation.REQUIRED)
    public void updateOrderStatus(Map<String, Object> paramMap) {
        //step1:获取封装数据
        String orderIds = String.valueOf(paramMap.get("orderIds"));
        Byte orderStatus = Byte.valueOf(String.valueOf(paramMap.get("orderStatus")));
        String statusName = String.valueOf(paramMap.get("statusName"));
        String cancelReason = String.valueOf(paramMap.get("cancelReason"));
        String userName = String.valueOf(paramMap.get("userName"));
        if (orderStatus == OrderModel.ORDER_STATUS_APPLY_REFUNDS) {//如果申请退款，插入退款信息
            java.lang.Double refundsPrice = java.lang.Double.valueOf(String.valueOf(paramMap
                .get("refundsPrice")));
            //添加订单退款
            OrderRefundsModel.validateRefundsPrice(orderIds, refundsPrice);
            OrderRefundsModel orderRefundsModel = new OrderRefundsModel();
            orderRefundsModel.setOrderId(Integer.valueOf(orderIds));
            orderRefundsModel.setRefundsPrice(refundsPrice);
            orderRefundsModel.setRefundsStatus(OrderRefundsModel.REFUNDS_STATUS_WAIT);
            orderRefundsModel.setCreatedName(userName);
            orderRefundsModel.setRefundsReason(cancelReason);
            this.orderDAO.insertOrderRefundsModel(orderRefundsModel);
        }
        //step2:数据校验
        OrderModel.validateUpdateOrderStatus(orderIds, orderStatus, statusName);
        //step3:查询订单状态
        String[] orderIdArray = orderIds.split(",");
        for (String orderIdStr : orderIdArray) {
            Integer orderId = Integer.valueOf(orderIdStr);
            OrderModel orderModel = this.orderDAO.selectOrderById(orderId);
            if (orderModel == null) {
                throw new ServiceException(OrderModel.ORDER_NO_EXISTS);
            }
            //step4:校验订单状态
            if (orderStatus <= orderModel.getOrderStatus().intValue()) {
                throw new ServiceException(OrderModel.ORDER_STARUS_EXCEPTION);
            }
            //step5:修改订单状态
            OrderModel orderMo = new OrderModel();
            orderMo.setId(orderId);
            orderMo.setOrderStatus(Byte.valueOf(String.valueOf(orderStatus)));
            orderMo.setUpdatedName(userName);
            if (orderStatus == OrderModel.ORDER_STATUS_APPLY_REFUNDS) {
                Byte beforeRefundOrderStatus = Byte.valueOf(String.valueOf(paramMap
                    .get("beforeRefundOrderStatus")));
                java.lang.Double refundsPrice = java.lang.Double.valueOf(String.valueOf(paramMap
                    .get("refundsPrice")));
                orderMo.setBeforeRefundOrderStatus(beforeRefundOrderStatus);
                orderMo.setRefundsPrice(refundsPrice);
            }
            if (StringUtils.isNotEmpty(cancelReason)) {
                if (OrderModel.ORDER_STATUS_APPLY_REFUNDS == orderStatus) {//已申请退款
                    orderMo.setRefundsReason(cancelReason);
                } else if (OrderModel.ORDER_STATUS_CNACEL == orderStatus) {//已取消
                    orderMo.setCancelName(userName);
                    orderMo.setCancelReason(cancelReason);
                }
            }
            this.orderDAO.updateOrderStatus(orderMo);

            //step6:添加物流状态信息
            LogisticStatusModel logisticStatusModel = new LogisticStatusModel();
            logisticStatusModel.setOrderId(orderId);
            logisticStatusModel.setStatusName(statusName);
            logisticStatusModel.setIsShow(LogisticStatusModel.LOGISTICS_STATUS_SHOW);
            logisticStatusModel.setCreatedName(userName);
            this.orderDAO.addLogisticStatus(logisticStatusModel);
            //step7:已确认订单推送通知消息
            //消息推送
            if (OrderModel.ORDER_STATUS_CONFIRMED == orderStatus) {
                if (orderIdArray.length > 0) {
                    String content = "";
                    if (orderIdArray.length == 1) {
                        content = "已有新的生产订单,订单号为" + orderId + "";
                    } else if (orderIdArray.length > 1) {
                        content = "已有新的生产订单,订单数为:" + orderIdArray.length;
                    }
                    String data = "{subscriberType:'"
                                  + CommonConstants.USER_ORDER_CONFIRM_SENDMESSAGE + "',orderId:'"
                                  + orderModel.getOrderCode() + "',title:'订单通知',content:'"
                                  + content + "'}";
                    SocketMessage.getInstance().sendMassge(data);
                }
                //已确认短信提醒
                String phone = orderModel.getConsignPhone();
                if (StringUtils.isNotEmpty(phone)) {
                    SmsConfirmOrder sms = new SmsConfirmOrder(phone, orderModel.getOrderCode());
                    if (SMSHelper.sendMessage(sms)) {
                        logger.info("订单:" + orderModel.getOrderCode() + "已确认");
                    }
                }
            } else if (OrderModel.ORDER_STATUS_SENDED == orderStatus) {//已发货短信提醒
                String phone = orderModel.getConsignPhone();
                //配送时间
                String deliveryDate = DateUtils.date2StrDate(orderModel.getDeliveryDate()) + " "
                                      + orderModel.getDeliveryTimes();
                if (StringUtils.isNotEmpty(phone)) {
                    SmsSendedOrder sms = new SmsSendedOrder(phone, orderModel.getOrderCode(),
                        deliveryDate);
                    if (SMSHelper.sendMessage(sms)) {
                        logger.info("订单:" + orderModel.getOrderCode() + "已发货");
                    }
                }
            }
            if (OrderModel.ORDER_REFUND_ORDER == orderStatus) {//已退款
                String phone = orderModel.getConsignPhone();
                SmsRefundOrder refundOrderSms = new SmsRefundOrder(phone, orderModel.getOrderCode());
                if (SMSHelper.sendMessage(refundOrderSms)) {
                    logger.info("订单:" + orderModel.getOrderCode() + "已退款");
                }
            }
        }
    }

    @Override
    @Transactional(rollbackFor = Exception.class, propagation = Propagation.REQUIRED)
    public void updateOrderLogisticNo(Map<String, Object> paramMap) {
        //step1:获取封装数据
        Integer orderId = Integer.valueOf(String.valueOf(paramMap.get("orderId")));
        String logisticNo = String.valueOf(paramMap.get("logisticNo"));
        String userName = String.valueOf(paramMap.get("userName"));
        //step2:数据校验
        OrderModel.validateUpdateOrderLogisticNo(orderId, logisticNo);
        //step3:修改物流状态
        OrderModel orderMo = new OrderModel();
        orderMo.setId(orderId);
        orderMo.setLogisticNo(logisticNo);
        orderMo.setUpdatedName(userName);
        this.orderDAO.updateOrderLogisticNo(orderMo);
    }

    @Override
    public List<LogisticStatusModel> queryLogisticStatus(Map<String, Object> map)
                                                                                 throws ServiceException {
        return this.orderDAO.queryLogisticStatus(map);
    }

    @Override
    public Long queryLogisticStatusCount(Map<String, Object> map) throws ServiceException {
        return this.orderDAO.queryLogisticStatusCount(map);
    }

    @Override
    public List<String> printThermalOrder(String htmlFilePath, Map<String, Object> map)
                                                                                       throws Exception {
        List<String> returnList = new ArrayList<String>();
        //step1:获取请求数据
        String orderId = String.valueOf(map.get("orderId"));
        //step2:数据校验
        OrderModel.validatePrintThermalValidate(orderId);
        //step3:查询订单信息
        List<OrderModel> listOrder = this.orderDAO.selectPrintThermalOrder(map);
        //step4:查询订单明细
        if (listOrder != null && listOrder.size() > 0) {
            Map<String, Object> orderDetailMap = new HashMap<String, Object>();
            for (OrderModel orderModel : listOrder) {
                //step5:查询商品对应全部配件信息
                orderDetailMap.put("goodsType", OrderDetailsModel.GOODS_TYPE_FIXINGS);
                orderDetailMap.put("orderId", orderModel.getId());
                List<OrderDetailsModel> listOrderDetailsFixing = this.orderDAO
                    .selectOrderDetailFixings(orderDetailMap);
                //配件信息
                String goodsFixingOrderName = OrderDetailsModel
                    .transGoodsFixingName(listOrderDetailsFixing);
                //订单编号条形码
                String orderCodeUrl = CommonConstants.PROJECT_PATH + "/barcode?msg="
                                      + orderModel.getOrderCode();
                //step6:按照商品以及规格查询订单明细信息
                orderDetailMap.put("goodsType", OrderDetailsModel.GOODS_TYPE_DEFALUT);
                List<OrderDetailsModel> listOrderDetailsModels = this.orderDAO
                    .selectOrderDetailByOrderId(orderDetailMap);
                //step7:每个商品打印一个热敏信息
                if (listOrderDetailsModels != null && listOrderDetailsModels.size() > 0) {
                    for (int i = 0, n = listOrderDetailsModels.size(); i < n; i++) {
                        OrderDetailsModel detailsModel = listOrderDetailsModels.get(i);
                        for (int j = 0; j < detailsModel.getGoodsNumber(); j++) {
                            String htmlCode = String.valueOf(i) + String.valueOf(j);
                            //商品编号条形码
                            String goodsStandardCodeUrl = CommonConstants.PROJECT_PATH
                                                          + "/barcode?msg="
                                                          + detailsModel.getGoodsStandardCode();
                            String filePostfix = orderModel.getOrderCode() + htmlCode + ".html";
                            //本地html保存路径
                            String localHtmlPath = htmlFilePath + File.separator + filePostfix;
                            Map<String, Object> mapParam = new HashMap<String, Object>();
                            mapParam.put("orders", orderModel);
                            mapParam.put("orderDetail", detailsModel);
                            mapParam.put("goodsNumber", 1);
                            mapParam
                                .put("goodsFixingOrderName", i == 0 ? goodsFixingOrderName : "");
                            mapParam.put("orderCodeUrl", orderCodeUrl);
                            mapParam.put("goodsStandardCodeUrl", goodsStandardCodeUrl);
                            //特殊处理,打印面单是正常宽度还是窄体宽度
                            String goodsId = String.valueOf(detailsModel.getGoodId());
                            boolean flag = false;
                            if (CommonConstants.DISTRIBUTION_SMALL_ORDER_ID.indexOf(goodsId) == -1) {//正常尺寸宽度
                                flag = FreeMarkerHelp.makeHtml("thetmalPrint.ftl", localHtmlPath,
                                    mapParam);
                            } else {//非正常尺寸宽度
                                flag = FreeMarkerHelp.makeHtml("peculiarThetmalPrint.ftl",
                                    localHtmlPath, mapParam);
                            }

                            if (flag) {
                                //静态页面可访问地址
                                String htmlUrl = "/html/" + filePostfix;
                                returnList.add(htmlUrl);
                            }
                        }
                    }
                }
            }
        }
        return returnList;
    }

    @Override
    public List<OrderModel> selectHandOverOrders(String orderIds) throws ServiceException {
        List<OrderModel> orderList = this.orderDAO.selectHandOverOrders(orderIds);
        // step3:为每个订单设置对应的订单详情列表
        for (int i = 0; i < orderList.size(); i++) {
            List<OrderDetailsModel> orderDetailList = this.orderDAO
                .selectHandOverOrderDetails(orderList.get(i).getId());
            orderList.get(i).setGoodsList(orderDetailList);
        }
        return orderList;
    }

    @Override
    public List<OrderDetailsModel> selectHandOverOrderDetails(Integer orderId)
                                                                              throws ServiceException {
        return this.orderDAO.selectHandOverOrderDetails(orderId);
    }

    @Override
    public void exportOrdersToExcel(HttpServletRequest request, HttpServletResponse response,
                                    List list) throws ServiceException {
        ExcelInfo info = new ExcelInfo();
        info.setColumnHeader("订单组号,商户名,商户合同,客户订单号 ,商品名称,单价,重量,数量,商品备注,订单应收总金,城市,配送日期,配送开始时间,配送结束时间,收货人 ,省,市,区,收货地址,手机号码,固定电话,支付方式,试吃公司名称,试吃申请人,试吃申请人电话,公司规模,配送备注");
        info.setFeilds(",,,orderCode,goodsName,goodsPrice,goodsWeight,goodsNumber,,,,deliveryDate,deliveryStartTimes,deliveryEndTimes,consignee,,,,consignAddress,consignPhone,,payTypeStr,companyName,applyUserName,applyUserPhone,companyScale,remark");
        info.setDatas(list);
        info.setSheetName("订单详情信息");
        info.setFileName(DateUtils.getStringToday() + "订单详情单");
        ExcelWriteHandle.getInstance().writeEcxcel(info, request, response);

    }

    @Override
    public List<OrderExcelModel> selectOrderExcelModel(String orderIds) throws ServiceException {
        return this.orderDAO.selectOrderExcelModel(orderIds);
    }

    @Override
    @Transactional(rollbackFor = Exception.class, propagation = Propagation.REQUIRED)
    public void updateOrderDeliveryInfo(Map<String, Object> map) throws ServiceException {
        //step1:获取请求信息
        Integer orderId = Integer.valueOf(String.valueOf(map.get("orderId")));
        String deliveryMan = String.valueOf(map.get("deliveryMan"));
        String deliveryMobileNo = String.valueOf(map.get("deliveryMobileNo"));
        String userName = String.valueOf(map.get("userName"));
        //step2:数据验证
        OrderModel.validateOrderDeliveryInfoParam(orderId, deliveryMan, deliveryMobileNo);
        //step3:添加物流信息
        OrderModel orderModel = this.orderDAO.selectOrderById(orderId);
        if (orderModel == null) {
            throw new ServiceException(OrderModel.ORDER_NO_EXISTS);
        }
        //配送时间
        String deliveryDate = DateUtils.date2StrDate(orderModel.getDeliveryDate()) + " "
                              + orderModel.getDeliveryTimes();
        //物流信息
        String logisticsMessage = MessageFormat.format(
            CommonConstants.ORDER_DELIVERY_LOGISTICS_MESSAGE, deliveryMan, deliveryDate,
            deliveryMobileNo);
        //step4:添加物流状态信息
        LogisticStatusModel logisticStatusModel = new LogisticStatusModel();
        logisticStatusModel.setOrderId(orderId);
        logisticStatusModel.setStatusName(logisticsMessage);
        logisticStatusModel.setIsShow(LogisticStatusModel.LOGISTICS_STATUS_SHOW);
        logisticStatusModel.setCreatedName(userName);
        this.orderDAO.addLogisticStatus(logisticStatusModel);
    }

    @Override
    public void updateOrderLogisticsMessage(Map<String, Object> map) throws ServiceException {
        //step1:获取请求信息
        Integer logisticId = Integer.valueOf(String.valueOf(map.get("logisticId")));
        String logisticMessage = String.valueOf(map.get("logisticMessage"));
        //step2:数据验证
        LogisticStatusModel.validateOrderLogisticsMessageParam(logisticId, logisticMessage);
        //step3:修改物流信息
        this.orderDAO.updateOrderLogisticsMessage(map);
    }

    @Override
    @Transactional(rollbackFor = Exception.class, propagation = Propagation.REQUIRED)
    public void updRefuseReceiveOrder(Map<String, Object> paramMap) throws ServiceException {
        // step1:获取封装数据
        String orderId = String.valueOf(paramMap.get("orderId"));
        Integer orderStatus = Integer.valueOf(String.valueOf(paramMap.get("orderStatus")));
        String userName = String.valueOf(paramMap.get("userName"));
        Integer orderType = Integer.valueOf(String.valueOf(paramMap.get("orderType")));
        String refundsReason = String.valueOf(paramMap.get("refundsReason"));
        // step2:数据校验
        OrderModel.validateUpdateRefuseOrderStatus(orderId, orderStatus, refundsReason);

        // step3:
        Integer id = Integer.valueOf(orderId);
        OrderModel orderModel = this.orderDAO.selectOrderById(id);
        if (orderModel == null) {
            throw new ServiceException(OrderModel.ORDER_NO_EXISTS);
        }
        // step4:校验订单状态
        if (orderStatus <= orderModel.getOrderStatus().intValue()) {
            throw new ServiceException(OrderModel.ORDER_STARUS_EXCEPTION);
        }

        if (orderStatus == OrderModel.ORDER_STATUS_APPLY_REFUNDS.intValue()) {//如果申请退款，插入退款信息
            java.lang.Double refundsPrice = java.lang.Double.valueOf(String.valueOf(paramMap
                .get("refundsPrice")));
            //添加订单退款
            OrderRefundsModel.validateRefundsPrice(orderId, refundsPrice);
            OrderRefundsModel orderRefundsModel = new OrderRefundsModel();
            orderRefundsModel.setOrderId(Integer.valueOf(orderId));
            orderRefundsModel.setRefundsPrice(refundsPrice);
            orderRefundsModel.setRefundsStatus(OrderRefundsModel.REFUNDS_STATUS_WAIT);
            orderRefundsModel.setCreatedName(userName);
            orderRefundsModel.setRefundsReason(refundsReason);
            this.orderDAO.insertOrderRefundsModel(orderRefundsModel);
        }

        // step5:修改订单状态
        //        this.orderDAO.updRefuseReceiveOrder(paramMap);
        OrderModel orderMo = new OrderModel();
        orderMo.setId(Integer.valueOf(orderId));
        orderMo.setOrderStatus(Byte.valueOf(String.valueOf(orderStatus)));
        orderMo.setUpdatedName(userName);
        if (orderStatus == OrderModel.ORDER_STATUS_APPLY_REFUNDS.intValue()) {
            Byte beforeRefundOrderStatus = Byte.valueOf(String.valueOf(paramMap
                .get("beforeRefundOrderStatus")));
            java.lang.Double refundsPrice = java.lang.Double.valueOf(String.valueOf(paramMap
                .get("refundsPrice")));
            orderMo.setBeforeRefundOrderStatus(beforeRefundOrderStatus);
            orderMo.setRefundsPrice(refundsPrice);
        }
        if (StringUtils.isNotEmpty(refundsReason)) {
            if (OrderModel.ORDER_STATUS_APPLY_REFUNDS.intValue() == orderStatus) {//已申请退款
                orderMo.setRefundsReason(refundsReason);
            } else if (OrderModel.ORDER_STATUS_CNACEL.intValue() == orderStatus) {//已取消
                orderMo.setCancelName(userName);
                orderMo.setCancelReason(refundsReason);
            }
        }
        this.orderDAO.updateOrderStatus(orderMo);

        // step6:添加拒收物流状态信息
        String logisticsMessage = LogisticStatusModel.STATUS_NAME_REFUSE + ",拒收理由:" + refundsReason;
        LogisticStatusModel logisticStatusModel = new LogisticStatusModel();
        logisticStatusModel.setOrderId(id);
        logisticStatusModel.setStatusName(logisticsMessage);
        logisticStatusModel.setIsShow(LogisticStatusModel.LOGISTICS_STATUS_SHOW);
        logisticStatusModel.setCreatedName(userName);
        this.orderDAO.addLogisticStatus(logisticStatusModel);

        // step7: 不为免单，再插入一条物流状态
        if (orderType != 3) {
            logisticStatusModel.setStatusName(LogisticStatusModel.STATUS_NAME_APPLY_BACK_MONEY);
            this.orderDAO.addLogisticStatus(logisticStatusModel);
        }
    }

    @Override
    public Map<String, Object> selectDayOrders() throws Exception {
        //返回参数信息
        Map<String, Object> returnMap = new HashMap<String, Object>();
        String orderStatus = OrderModel.getDayOrderStatus();
        //step1:获取前一天和今天日期时间
        String preDayTime = DateUtils.getOneTimeDate(-1, 16);
        String nowDayTime = DateUtils.getOneTimeDate(0, 16);
        //step2:查询订单信息
        Map<String, Object> paramMap = new HashMap<String, Object>();
        paramMap.put("orderStatus", orderStatus);
        paramMap.put("preDayTime", preDayTime);
        paramMap.put("nowDayTime", nowDayTime);
        List<OrderModel> orderList = this.orderDAO.selectDayOrders(paramMap);
        if (orderList != null && orderList.size() > 0) {
            // step3:订单详情
            double totalAmountSum = 0.00; // 订单总额
            double payAmountSum = 0.00; // 支付总额
            Integer goodsNumberSum = 0; // 商品总数
            for (OrderModel orderInfo : orderList) {
                List<OrderDetailsModel> orderDetailList = this.orderDAO
                    .selectDetailsByOrderId(orderInfo.getId());
                orderInfo.setGoodsList(orderDetailList);
                totalAmountSum += orderInfo.getTotalAmount();
                payAmountSum += orderInfo.getPayAmount();
                goodsNumberSum += orderInfo.getGoodsNumber();
            }

            // step4:模板参数
            Map<String, Object> orderMap = new HashMap<String, Object>();
            orderMap.put("orderList", orderList);
            orderMap.put("preDayTime", preDayTime);
            orderMap.put("nowDayTime", nowDayTime);
            orderMap.put("totalAmountSum", totalAmountSum);
            orderMap.put("payAmountSum", payAmountSum);
            orderMap.put("goodsNumberSum", goodsNumberSum);
            String templateHtml = FreeMarkerHelp.getTemplateHtml(orderMap, "dayMessage.ftl");
            returnMap.put("isOrderCount", true);
            returnMap.put("templateHtml", templateHtml);
        } else {
            returnMap.put("isOrderCount", false);
        }
        return returnMap;
    }

    @Override
    public Map<String, Object> statisticsOrderReport() throws Exception {
        Map<String, Object> returnMap = new HashMap<String, Object>();
        //step1:报表参数信息
        Map<String, Object> orderReportMap = new HashMap<String, Object>();
        //获取订单查询数据
        String orderStatus = OrderModel.getDayOrderStatus();
        //非免费订单订单类型
        String orderTypeNoFree = "0,1,6,7,8";
        //订单按照时间段统计订单类型
        String orderTimeOrderType = "0,1,2,3,4,5,6,7,8";
        //免费订单
        String orderTypeFree = "2,3";
        //获取前一天日期
        Date nightBeforDate = DateUtils.getSomeDayDate(-1);
        String reportDate = DateUtils.getEnglishDateTime(nightBeforDate);
        String nightBeforDateString = DateUtils.date2StrDate(nightBeforDate);
        orderReportMap.put("reportDate", reportDate);
        Map<String, Object> paramMap = new HashMap<String, Object>();

        //邮件统计报表返回集合
        List<OrderReportModel> listOrderReportModels = new ArrayList<OrderReportModel>();
        //step2:查询B2cSales订单数据当天
        paramMap.put("orderStatus", orderStatus);
        paramMap.put("orderType", orderTypeNoFree);//0:普通订单 1:企业订单 6:点评(美团)订单
        paramMap.put("categoryType", "0");
        paramMap.put("createDate", nightBeforDateString);
        OrderReportModel b2cSalesModel = this.statisticDAO.selectB2cOrderReportByStatus(paramMap);
        //查询b2c已退款完成的订单信息
        paramMap.put("orderStatusRefunds", "9");//9.已退款
        OrderReportModel b2cSalesRefunds = this.statisticDAO.selectB2cOrderRefunds(paramMap);
        paramMap.put("isDelete", "0");
        OrderReportModel b2bSalesModel = this.statisticDAO.selectB2bOrderReportByStatus(paramMap);
        //查询b2b补差价订单信息
        paramMap.put("orderTypeB2b", "4");//4：B2B订单
        OrderReportModel b2bDifferenceModel = this.statisticDAO.selectB2bOrderDifference(paramMap);
        //b2b退款（orderTypeB2b=4，orderStatusRefunds=9）
        OrderReportModel b2bSalesRefunds = this.statisticDAO.selectB2bOrderRefunds(paramMap);
        //step3:封装B2cSales数据
        b2cSalesModel.setOrderReview("Daily Sales");
        //b2c
        b2cSalesModel.setB2cPayAmount(b2cSalesModel.getB2cPayAmount()
                                      + (b2cSalesRefunds.getB2cPayAmount() - b2cSalesRefunds
                                          .getOrderRefundPrice()));//今天实收金额-今天退款金额
        //b2b
        b2cSalesModel.setB2bOrderNum(b2bSalesModel.getB2bOrderNum());
        b2cSalesModel.setB2bTotalAmount(b2bSalesModel.getB2bTotalAmount());
        b2cSalesModel.setB2bPayAmount(b2bSalesModel.getB2bPayAmount()
                                      + b2bDifferenceModel.getB2bPayAmount()
                                      - b2bSalesRefunds.getOrderRefundPrice());
        //行 总计
        b2cSalesModel
            .setTotalOrder(b2cSalesModel.getB2cOrderNum() + b2cSalesModel.getB2bOrderNum());
        b2cSalesModel.setTotalAmount(b2cSalesModel.getB2cTotalAmount()
                                     + b2cSalesModel.getB2bTotalAmount());
        b2cSalesModel.setPayAmount(b2cSalesModel.getB2bPayAmount()
                                   + b2cSalesModel.getB2cPayAmount());
        listOrderReportModels.add(b2cSalesModel);
        //step4:b2c Free数据处理
        paramMap.put("orderType", orderTypeFree);
        OrderReportModel b2cFreeModel = this.statisticDAO.selectB2cOrderReportByStatus(paramMap);
        b2cFreeModel.setOrderReview("Free");
        b2cFreeModel.setB2bOrderNum(0);
        b2cFreeModel.setB2bTotalAmount(java.lang.Double.valueOf("0"));
        b2cFreeModel.setB2bPayAmount(java.lang.Double.valueOf("0"));
        b2cFreeModel.setTotalOrder(b2cFreeModel.getB2cOrderNum() + b2cFreeModel.getB2bOrderNum());
        b2cFreeModel.setTotalAmount(b2cFreeModel.getB2cTotalAmount()
                                    + b2cFreeModel.getB2bTotalAmount());
        b2cFreeModel.setPayAmount(b2cFreeModel.getB2bPayAmount() + b2cFreeModel.getB2cPayAmount());
        listOrderReportModels.add(b2cFreeModel);
        //step5:total总计
        if (listOrderReportModels != null && listOrderReportModels.size() > 0) {
            OrderReportModel totalModel = new OrderReportModel();
            int sumb2cOrder = 0;
            double sumB2cTotalAmount = 0;
            double sumB2cPayAmount = 0;
            int sumb2bOrder = 0;
            double sumB2bTotalAmount = 0;
            double sumB2bPayAmount = 0;
            int sumOrder = 0;
            double sumTotalAmount = 0;
            double sumPayAmount = 0;
            for (OrderReportModel reportModel : listOrderReportModels) {
                sumb2cOrder += reportModel.getB2cOrderNum();
                sumB2cTotalAmount += reportModel.getB2cTotalAmount();
                sumB2cPayAmount += reportModel.getB2cPayAmount();
                sumb2bOrder += reportModel.getB2bOrderNum();
                sumB2bTotalAmount += reportModel.getB2bTotalAmount();
                sumB2bPayAmount += reportModel.getB2bPayAmount();
                sumOrder += reportModel.getTotalOrder();
                sumTotalAmount += reportModel.getTotalAmount();
                sumPayAmount += reportModel.getPayAmount();
            }
            totalModel.setOrderReview("Total");
            totalModel.setB2cOrderNum(sumb2cOrder);
            totalModel.setB2cTotalAmount(sumB2cTotalAmount);
            totalModel.setB2cPayAmount(sumB2cPayAmount);
            totalModel.setB2bOrderNum(sumb2bOrder);
            totalModel.setB2bTotalAmount(sumB2bTotalAmount);
            totalModel.setB2bPayAmount(sumB2bPayAmount);
            totalModel.setTotalOrder(sumOrder);
            totalModel.setTotalAmount(sumTotalAmount);
            totalModel.setPayAmount(sumPayAmount);
            listOrderReportModels.add(totalModel);
        }
        //step6:本月订单数据统计This Month
        paramMap.put("orderType", orderTypeNoFree);
        paramMap.put("categoryType", "1");
        paramMap.put("createDate", DateUtils.transYearMonth(nightBeforDate));
        OrderReportModel b2cMonthModel = this.statisticDAO.selectB2cOrderReportByStatus(paramMap);
        //查询b2c已退款完成的订单信息
        paramMap.put("orderStatusRefunds", "9");//9.已退款
        OrderReportModel b2cSalesRefundsMonth = this.statisticDAO.selectB2cOrderRefunds(paramMap);
        paramMap.put("isDelete", "0");
        OrderReportModel b2bMonthModel = this.statisticDAO.selectB2bOrderReportByStatus(paramMap);
        //查询b2b补差价订单信息
        paramMap.put("orderTypeB2b", "4");//4：B2B订单
        OrderReportModel b2bDifferenceMonth = this.statisticDAO.selectB2bOrderDifference(paramMap);
        //b2b退款（orderTypeB2b=4，orderStatusRefunds=9）
        OrderReportModel b2bSalesRefundsMonth = this.statisticDAO.selectB2bOrderRefunds(paramMap);
        //step7:封装This Month数据
        b2cMonthModel.setOrderReview("Month-to-Date Sales");
        //b2c
        b2cMonthModel.setB2cOrderNum(b2cMonthModel.getB2cOrderNum()
                                     - b2cSalesRefundsMonth.getOrderRefundCount());
        b2cMonthModel.setB2cTotalAmount(b2cMonthModel.getB2cTotalAmount()
                                        + b2cSalesRefundsMonth.getB2cTotalAmount());
        b2cMonthModel
            .setB2cPayAmount(b2cMonthModel.getB2cPayAmount()
                             + (b2cSalesRefundsMonth.getB2cPayAmount() - b2cSalesRefundsMonth
                                 .getOrderRefundPrice()));
        //b2b
        b2cMonthModel.setB2bOrderNum(b2bMonthModel.getB2bOrderNum());
        b2cMonthModel.setB2bTotalAmount(b2bMonthModel.getB2bTotalAmount());
        b2cMonthModel.setB2bPayAmount(b2bMonthModel.getB2bPayAmount()
                                      + b2bDifferenceMonth.getB2bPayAmount()
                                      - b2bSalesRefundsMonth.getOrderRefundPrice());
        //行 总计
        b2cMonthModel
            .setTotalOrder(b2cMonthModel.getB2cOrderNum() + b2cMonthModel.getB2bOrderNum());
        b2cMonthModel.setTotalAmount(b2cMonthModel.getB2cTotalAmount()
                                     + b2cMonthModel.getB2bTotalAmount());
        b2cMonthModel.setPayAmount(b2cMonthModel.getB2cPayAmount()
                                   + b2cMonthModel.getB2bPayAmount());
        listOrderReportModels.add(b2cMonthModel);
        //step8:年订单数据统计This Year
        paramMap.put("orderType", orderTypeNoFree);
        paramMap.put("categoryType", "2");
        paramMap.put("createDate", DateUtils.transYear(nightBeforDate));
        OrderReportModel b2cYearModel = this.statisticDAO.selectB2cOrderReportByStatus(paramMap);
        //查询b2c已退款完成的订单信息
        paramMap.put("orderStatusRefunds", "9");//9.已退款
        OrderReportModel b2cSalesRefundsYear = this.statisticDAO.selectB2cOrderRefunds(paramMap);
        paramMap.put("isDelete", "0");
        OrderReportModel b2bYearModel = this.statisticDAO.selectB2bOrderReportByStatus(paramMap);
        //查询b2b补差价订单信息
        paramMap.put("orderTypeB2b", "4");//4：B2B订单
        OrderReportModel b2bDifferenceYear = this.statisticDAO.selectB2bOrderDifference(paramMap);
        //b2b退款（orderTypeB2b=4，orderStatusRefunds=9）
        OrderReportModel b2bSalesRefundsYear = this.statisticDAO.selectB2bOrderRefunds(paramMap);
        //step9:封装This Year数据
        b2cYearModel.setOrderReview("Year-to-Date Sales");
        //B2C
        b2cYearModel.setB2cOrderNum(b2cYearModel.getB2cOrderNum()
                                    - b2cSalesRefundsYear.getOrderRefundCount());
        b2cYearModel.setB2cTotalAmount(b2cYearModel.getB2cTotalAmount()
                                       + b2cSalesRefundsYear.getB2cTotalAmount());
        b2cYearModel.setB2cPayAmount(b2cYearModel.getB2cPayAmount()
                                     + (b2cSalesRefundsYear.getB2cPayAmount() - b2cSalesRefundsYear
                                         .getOrderRefundPrice()));
        //B2B
        b2cYearModel.setB2bOrderNum(b2bYearModel.getB2bOrderNum());
        b2cYearModel.setB2bTotalAmount(b2bYearModel.getB2bTotalAmount());
        b2cYearModel.setB2bPayAmount(b2bYearModel.getB2bPayAmount()
                                     + b2bDifferenceYear.getB2bPayAmount()
                                     - b2bSalesRefundsYear.getOrderRefundPrice());
        //行总计
        b2cYearModel.setTotalOrder(b2cYearModel.getB2cOrderNum() + b2cYearModel.getB2bOrderNum());
        b2cYearModel.setTotalAmount(b2cYearModel.getB2cTotalAmount()
                                    + b2cYearModel.getB2bTotalAmount());
        b2cYearModel.setPayAmount(b2cYearModel.getB2cPayAmount() + b2cYearModel.getB2bPayAmount());
        listOrderReportModels.add(b2cYearModel);

        orderReportMap.put("orderReport", listOrderReportModels);

        //step10:订单时间段统计
        paramMap.put("orderType", orderTimeOrderType);
        paramMap.put("createDate", DateUtils.date2StrDate(nightBeforDate));
        List<OrderReportDateTimeModel> orderTimeModels = this.statisticDAO
            .selectOrderReportTimeTotal(paramMap);
        orderReportMap.put("orderTimeReport", orderTimeModels);
        //step11:订单销售明细统计
        List<OrderReportGoodsModel> listreReportGoodsModels = this.statisticDAO
            .selectOrderReportGoodsTotal(paramMap);
        orderReportMap.put("orderGoodsReport", listreReportGoodsModels);
        double sumAllOrderAmount = 0;
        if (listreReportGoodsModels != null && listreReportGoodsModels.size() > 0) {
            for (OrderReportGoodsModel goodsModel : listreReportGoodsModels) {
                sumAllOrderAmount += goodsModel.getTotalAmount();
            }
        }
        orderReportMap.put("sumAllOrderAmount", sumAllOrderAmount);
        //step12:销售额统计图当月
        paramMap.put("createDate", DateUtils.transYearMonth(nightBeforDate));
        List<FusionChartsModel> listOrderTotalAmount = this.statisticDAO
            .selectOrderAmountByMonth(paramMap);
        orderReportMap.put("listOrderTotalAmount",
            JsonUtil.writeObjectNoPageJSON(listOrderTotalAmount));
        //step12:销售数量饼图统计当天
        paramMap.put("createDate", DateUtils.date2StrDate(nightBeforDate));
        List<FusionChartsModel> listOrderGoodsAmount = this.statisticDAO
            .selectOrderGoodsNumAmountByMonth(paramMap);
        orderReportMap.put("listOrderGoodsAmount",
            JsonUtil.writeObjectNoPageJSON(listOrderGoodsAmount));
        //step13:生成html报表
        //临时保存路径
        String freeMarketFoderPath = Tools.getRootPath();
        logger.error("本地html保存地址：" + freeMarketFoderPath);
        String filePostfix = CommonConstants.MM_ORDER_REPORT_FILE_NAME + "-MM-Sales-Report"
                             + nightBeforDateString + ".html";
        String localHtmlPath = freeMarketFoderPath + File.separator + filePostfix;
        boolean flag = FreeMarkerHelp.makeHtml("orderReport.ftl", localHtmlPath, orderReportMap);
        String orderReportUrl = "";
        if (flag) {//上传
            File localFile = new File(localHtmlPath);
            QiNiuResponse response = QiNiuGoodsPicTemplate.uploadFileInfo(localFile, filePostfix);
            if (!response.isSuccess()) {
                throw new ServiceException(GoodsModel.UPLOAD_FILE_FAILURE);
            } else {
                //删除本地文件
                if (localFile.isFile() && localFile.exists()) {
                    localFile.delete();
                }
            }
            orderReportUrl = QiNiuGoodsPicTemplate.getFileDownloadUrl(response.key);
        }
        returnMap.put("orderReportUrl", orderReportUrl);
        return returnMap;
    }

    @Override
    public List<GoodOrderModel> selectGoodsPrize(Map<String, Object> map) throws ServiceException {
        List<GoodOrderModel> list = this.orderDAO.selectGoodsPrize(map);
        if (list != null && list.size() > 0) {
            for (GoodOrderModel orderModel : list) {
                orderModel.setGoodsNumber(1);
            }
        }
        return list;
    }

    @Override
    public Long selectGoodsPrizeCount(Map<String, Object> map) throws Exception {
        return this.orderDAO.selectGoodsPrizeCount(map);
    }

    @Override
    public void initBaiduRangeInfo() {
        //查询全部经纬度数据
        Map<String, Object> paramMap = new HashMap<String, Object>();
        paramMap.put("isEnable", BaiduRangeParamModel.IS_ENABLE_YES);
        List<BaiduRangeParamModel> listRangeParamModels = this.orderDAO
            .selectBaiduRangeInfoList(paramMap);
        if (listRangeParamModels != null && listRangeParamModels.size() > 0) {
            List<Point2D.Double> pts = new ArrayList<Point2D.Double>();
            for (int i = 0, n = listRangeParamModels.size(); i < n; i++) {
                BaiduRangeParamModel paramModel = listRangeParamModels.get(i);
                pts.add(new Point2D.Double(paramModel.getLongitude(), paramModel.getLatitude()));
            }
            BaiduMapRangeCache.getInstance().put("pts", pts);
        }
    }

    @Override
    @Transactional(rollbackFor = Exception.class, propagation = Propagation.REQUIRED)
    public void saveOrder(GoodOrderModel goodOrderModel, String jsonList, String userName)
                                                                                          throws Exception {
        List<GoodOrderModel> list = JsonUtil.returnObjectList(jsonList, GoodOrderModel.class);

        Map<String, Object> rangeMap = getAddrrssScope(goodOrderModel.getDistrictName(),
            goodOrderModel.getAddress());
        if (rangeMap == null || Integer.parseInt(String.valueOf(rangeMap.get("isScope"))) == 0) {//不在配送范围内
            throw new ServiceException(String.valueOf(rangeMap.get("message")));
        }
        String longitude = String.valueOf(rangeMap.get("longitude"));//精度
        String latitude = String.valueOf(rangeMap.get("latitude"));//维度
        //订单实际支付金额
        double payment = goodOrderModel.getPayAmount() == null ? 0 : goodOrderModel.getPayAmount();

        OrderDetailsModel detailsModel = new OrderDetailsModel();
        //拼装订单信息
        OrderModel orderModel = new OrderModel();
        int userId = Integer.parseInt(CommonConstants.USER_ID);
        orderModel.setUserId(userId);
        orderModel.setOrderType(goodOrderModel.getOrderType());
        orderModel.setPayStatus(OrderModel.ORDER_STATUS_PAY);
        orderModel.setPayType(OrderModel.PAY_TYPE_NULL);
        orderModel.setCreatedName(userName);
        String ConsignAddress = goodOrderModel.getCityName() + goodOrderModel.getDistrictName()
                                + goodOrderModel.getAddress();
        orderModel.setConsignAddress(ConsignAddress);
        orderModel.setConsignee(goodOrderModel.getConsignee());
        orderModel.setConsignPhone(goodOrderModel.getConsignPhone());
        orderModel.setDeliveryDate(goodOrderModel.getDeliveryDate());
        if (goodOrderModel.getOrderType() == 8
            || goodOrderModel.getOrderFinish().equals(OrderModel.ORDER_FINISH)) {//当日订单直接变为已发货
            orderModel.setOrderStatus(OrderModel.ORDER_STATUS_SENDED);
        } else {
            orderModel.setOrderStatus(OrderModel.ORDER_STATUS_CONFIRM);
        }
        orderModel.setBirthdayCard(goodOrderModel.getBirthdayCard());
        orderModel.setRemark(goodOrderModel.getRemark());
        orderModel.setDeliveryFee(goodOrderModel.getDeliveryFee());
        orderModel.setPayDate(DateUtils.getDateStamp());
        orderModel.setDeliveryTimes(goodOrderModel.getDeliveryTimes());
        orderModel.setCouponType(goodOrderModel.getCouponType());
        orderModel.setLatitude(latitude);
        orderModel.setLongitude(longitude);
        if (goodOrderModel.getOrderType() == 4) {//B2B订单
            //根据劵码查询优惠券信息
            String couponCode = goodOrderModel.getCouponCode();
            if (StringUtils.isEmpty(couponCode)) {
                throw new ServiceException(OrderModel.COUPON_CODE_IS_NULL);
            }
            Map<String, Object> couponParamMap = new HashMap<String, Object>();
            couponParamMap.put("couponCode", couponCode.toUpperCase().trim());
            couponParamMap.put("couponStatus", CouponModel.COUPON_STATUS_NO_USER);
            couponParamMap.put("isEnable", CouponModel.COUPON_IS_ENABLE_YES);
            CouponModel couponModel = this.couponDAO.selectCouponByCouponCode(couponParamMap);
            if (couponModel == null) {
                throw new ServiceException(CouponModel.COUPON_NOT_USERS);
            }
            orderModel.setPayAmount(0d);
            orderModel.setCouponId(couponModel.getId());
            orderModel.setCouponCode(couponCode.toUpperCase().trim());
            orderModel.setCouponType(Byte.valueOf("2"));
            //作废已使用的优惠码
            if (CouponModel.COUPON_SINGLE_YES.equals(couponModel.getIsSingleUser())) {
                Map<String, Object> couponMap = new HashMap<String, Object>();
                couponMap.put("couponId", couponModel.getId());
                couponMap.put("couponStatus", CouponModel.COUPON_STATUS_ALREADY_USER);
                couponMap.put("isEnable", CouponModel.COUPON_IS_ENABLE_NO);
                couponMap.put("updateName", userName);
                this.couponDAO.updateCouponCodeStatus(couponMap);
            }
        } else {
            orderModel.setCouponCode(goodOrderModel.getCouponCode().toUpperCase().trim());
            orderModel.setCouponFee(goodOrderModel.getCouponFee());
            orderModel.setPayAmount(payment);
            orderModel.setCouponId(null);
        }
        orderModel.setApplyUserName(goodOrderModel.getApplyUserName());
        orderModel.setApplyUserPhone(goodOrderModel.getApplyUserPhone());
        orderModel.setCompanyName(goodOrderModel.getCompanyName());
        orderModel.setCompanyScale(goodOrderModel.getCompanyScale());
        this.orderDAO.insertOrder(orderModel);
        int goodsNumber = 0;
        double subTotal = 0;
        double totalAmount = 0;
        int giveGoodsfixingNum = 0;
        //计算差额
        double orderMonmey = payment;
        //step:查询配件集合信息
        Map<String, Object> map = new HashMap<String, Object>();
        map.put("isEnable", 0);
        map.put("fixingType", GoodsFixingModel.FIXING_TYPE_GIVE);
        List<GoodsFixingModel> fixingModels = this.fixingDAO.selectFixingsByFixingType(map);
        //拼装订单明细信息
        OrderDetailsModel dModel = new OrderDetailsModel();

        for (GoodOrderModel goodOrder : list) {
            detailsModel.setOrderId(orderModel.getId());
            detailsModel.setGoodId(goodOrder.getGoodsId());
            detailsModel.setGoodsCode(goodOrder.getGoodsCode());
            detailsModel.setGoodsName(goodOrder.getGoodsName());
            detailsModel.setGoodsStandardCode(goodOrder.getGoodsStandardCode());
            detailsModel.setGoodsPrice(goodOrder.getGoodsPrice());
            detailsModel.setGoodsSize(goodOrder.getGoodsSize());
            detailsModel.setGoodsWeight(goodOrder.getGoodsWeight());
            detailsModel.setGoodsNumber(goodOrder.getGoodsNumber());
            detailsModel.setGoodsType(OrderDetailsModel.GOODS_TYPE_DEFALUT);
            goodsNumber += goodOrder.getGoodsNumber();
            subTotal = goodOrder.getGoodsNumber() * goodOrder.getGoodsPrice();
            detailsModel.setSubTotal(subTotal);
            totalAmount += subTotal;
            if (goodOrderModel.getOrderType() != 2 && goodOrderModel.getOrderType() != 3) {//排除免费和试吃订单
                if (orderMonmey > subTotal) {
                    detailsModel.setPaySubTotal(subTotal);
                    orderMonmey = orderMonmey - subTotal;
                } else {
                    detailsModel.setPaySubTotal(orderMonmey);
                }
            } else {
                detailsModel.setPaySubTotal(java.lang.Double.valueOf(0));
            }
            detailsModel.setGoodsUnits(goodOrder.getGoodsUnits());
            this.orderDAO.insertOrderDetail(detailsModel);
            if (goodOrder.getGiveLaidNumber() > 0) {
                for (GoodsFixingModel fixingModel : fixingModels) {
                    //配件总数
                    giveGoodsfixingNum += goodOrder.getGiveLaidNumber()
                                          * fixingModel.getFixingMultiple()
                                          * goodOrder.getGoodsNumber();
                    dModel.setGoodId(fixingModel.getId());
                    dModel.setOrderId(orderModel.getId());
                    dModel.setGoodsCode(fixingModel.getFixingCode());
                    dModel.setGoodsStandardCode(fixingModel.getFixingCode());
                    dModel.setGoodsName(fixingModel.getFixingName());
                    dModel.setGoodsPrice(fixingModel.getFixingPrice());
                    dModel.setGoodsUnits(fixingModel.getFixingUnits());
                    dModel.setGoodsType(OrderDetailsModel.GOODS_TYPE_FIXINGS);
                    double fixTotal = giveGoodsfixingNum * fixingModel.getFixingPrice();
                    dModel.setSubTotal(fixTotal);
                }
                dModel.setGoodsNumber(giveGoodsfixingNum);
            }
        }

        this.orderDAO.insertOrderDetail(dModel);

        //step:添加流水
        UserPaymentsModel paymentsModel = new UserPaymentsModel();
        paymentsModel.setUserId(userId);
        paymentsModel.setOrderId(orderModel.getId());
        paymentsModel.setTotalAmount(payment);
        paymentsModel.setStatus(UserPaymentsModel.PAYMENT_STATUS_SUCCESS);
        paymentsModel.setPayWays(goodOrderModel.getPayType());
        paymentsModel.setPayNo("10000");
        this.orderDAO.addUserPayments(paymentsModel);

        //step:设置订单编码
        int orderId = orderModel.getId();
        String orderCode = "OT" + DateUtils.getCurrentFormatDateTime() + orderId;
        Map<String, Object> paramMap = new HashMap<String, Object>();
        paramMap.put("orderCode", orderCode);
        paramMap.put("orderId", orderId);
        paramMap.put("goodsNumber", goodsNumber);
        paramMap.put("userPaymentId", paymentsModel.getId());
        paramMap.put("totalAmount", totalAmount);
        if (goodOrderModel.getOrderType() == 4) {//B2B订单
            paramMap.put("couponFee", totalAmount);
        }
        this.orderDAO.updateOrderCode(paramMap);
        //针对 点评(美团)等订单单独发送短信
        if (goodOrderModel.getOrderType() == 6 || goodOrderModel.getOrderType() == 7
            || goodOrderModel.getOrderType() == 8 || goodOrderModel.getOrderType() == 4) {//6:点评(美团)订单,7:生日管家订单,8:当日订单,4:B2B订单
            //配送时间
            String deliveryDate = DateUtils.date2StrDate(goodOrderModel.getDeliveryDate()) + " "
                                  + goodOrderModel.getDeliveryTimes();
            if (StringUtils.isNotEmpty(goodOrderModel.getConsignPhone())) {
                SmsCreateOrder sms = new SmsCreateOrder(goodOrderModel.getConsignPhone(),
                    orderCode, deliveryDate);
                if (SMSHelper.sendMessage(sms)) {
                    logger.info("订单:" + orderModel.getOrderCode() + "已下单");
                }
            }
        }
    }

    @SuppressWarnings("unchecked")
    public Map<String, Object> getAddrrssScope(String districtName, String address) {
        Map<String, Object> returnMap = new HashMap<String, Object>();
        //step2:数据校验
        if (StringUtils.isEmpty(address)) {
            throw new ServiceException(UserAddressModel.ADDRESS_NOE_NULL);
        }
        //step3:获取缓存中的经纬度
        List<Point2D.Double> pts = (List<Double>) BaiduMapRangeCache.getInstance().get("pts");
        //step4:获取当前地址经纬度
        Map<String, String> addMap = BaiduLatitudeHelp.getGeocoderLatitude(address);
        if (addMap == null) {
            returnMap.put("isScope", 0);
            returnMap.put("message", "抱歉，您的地址输入有误，无法获取该地址坐标");
            return returnMap;
        }
        String longitude = addMap.get("lng");
        String latitude = addMap.get("lat");
        if (StringUtils.isEmpty(latitude) || StringUtils.isEmpty(longitude)) {
            returnMap.put("isScope", 0);
            returnMap.put("message", "抱歉，您的地址输入有误，无法获取该地址坐标");
            return returnMap;
        }
        //step5:获取当前地址所对应的区
        String location = latitude + "," + longitude;
        Map<String, String> locationMap = BaiduLatitudeHelp.getLatitudeGeocoder(location);
        if (locationMap == null) {
            returnMap.put("isScope", 0);
            returnMap.put("message", "抱歉，您的地址输入有误，无法获取该地址坐标");
            return returnMap;
        }
        String district = locationMap.get("district");//区县信息
        if (StringUtils.isEmpty(district)) {
            returnMap.put("isScope", 0);
            returnMap.put("message", "抱歉，无法定位地址所对应的区县信息");
            return returnMap;
        }
        //区县特殊处理，如果百度地图返回的是"闸北区",则统一默认为静安区
        if ("闸北区".equals(district)) {
            district = "静安区";
        }
        if (!districtName.equals(district)) {
            returnMap.put("isScope", 0);
            returnMap.put("message", "抱歉，您的地址输入有误，当前地址所在地区是:" + district);
            return returnMap;
        }

        Point2D.Double point = new Point2D.Double(java.lang.Double.parseDouble(longitude),
            java.lang.Double.parseDouble(latitude));
        if (PtInPolyHelp.IsPtInPoly(point, pts)) {
            returnMap.put("isScope", 1);
            returnMap.put("longitude", longitude);
            returnMap.put("latitude", latitude);
            returnMap.put("message", "该地址为外环内地址");
        } else {
            returnMap.put("isScope", 0);
            returnMap.put("message", "抱歉，该地址暂时不在配送范围哦");
        }
        return returnMap;
    }

    @Override
    public List<OrderRefundsModel> selectOrderRefundsList(Map<String, Object> paramerMap)
                                                                                         throws Exception {
        return this.orderDAO.selectOrderRefundsList(paramerMap);
    }

    @Override
    public Long selectOrderRefundsCount(Map<String, Object> paramerMap) throws Exception {
        return this.orderDAO.selectOrderRefundsCount(paramerMap);
    }

    @Override
    public void updateOrderRefundsStatus(OrderRefundsModel orderRefundsModel) throws Exception {
        this.orderDAO.updateOrderRefundsStatus(orderRefundsModel);
    }

    @Override
    public void updateOrderRefundsStatus(Map<String, Object> paramMap) throws ServiceException {
        //step1:获取封装数据
        String Ids = String.valueOf(paramMap.get("ids"));
        Byte refundsStatus = Byte.valueOf(String.valueOf(paramMap.get("refundsStatus")));
        String userName = String.valueOf(paramMap.get("userName"));
        String refusedReason = String.valueOf(paramMap.get("refusedReason"));
        String statusName = String.valueOf(paramMap.get("statusName"));
        String orderStatusArr = String.valueOf(paramMap.get("orderStatusArr"));
        String[] orderStatusArray = orderStatusArr.split(",");
        //step2:查询订单状态
        String[] IdArray = Ids.split(",");
        for (String IdStr : IdArray) {
            Integer id = Integer.valueOf(IdStr);
            OrderRefundsModel or = this.orderDAO.selectOrderRefundsById(id);
            //step3:修改订单状态
            OrderRefundsModel orderRefundsModel = new OrderRefundsModel();
            orderRefundsModel.setId(id);
            orderRefundsModel.setRefundsStatus(Byte.valueOf(String.valueOf(refundsStatus)));
            orderRefundsModel.setUpdatedName(userName);
            if (refusedReason != "null") {
                orderRefundsModel.setRefusedReason(refusedReason);
            }
            this.orderDAO.updateOrderRefundsStatus(orderRefundsModel);
            OrderModel om = new OrderModel();
            if (refundsStatus == OrderRefundsModel.REFUNDS_STATUS_WAIT) {
                om.setOrderStatus(OrderModel.ORDER_STATUS_APPLY_REFUNDS);
                om.setUpdatedName(userName);
                om.setId(or.getOrderId());
                this.orderDAO.updateOrderStatus(om);
            } else if (refundsStatus == OrderRefundsModel.REFUNDS_STATUS_CONFIRM) {
                om.setOrderStatus(OrderModel.ORDER_REFUNDING_ORDER);
                om.setUpdatedName(userName);
                om.setId(or.getOrderId());
                this.orderDAO.updateOrderStatus(om);
            } else if (refundsStatus == OrderRefundsModel.REFUNDS_STATUS_CONFIRMED) {
                om.setOrderStatus(OrderModel.ORDER_REFUND_ORDER);
                om.setUpdatedName(userName);
                om.setId(or.getOrderId());
                this.orderDAO.updateOrderStatus(om);
            }
            //step4:添加物流状态信息
            LogisticStatusModel logisticStatusModel = new LogisticStatusModel();
            logisticStatusModel.setOrderId(or.getOrderId());
            logisticStatusModel.setStatusName(statusName);
            logisticStatusModel.setIsShow(LogisticStatusModel.LOGISTICS_STATUS_SHOW);
            logisticStatusModel.setCreatedName(userName);
            this.orderDAO.addLogisticStatus(logisticStatusModel);

            if (refundsStatus == OrderRefundsModel.REFUNDS_STATUS_REFUSED) {//拒绝订单，订单状态改回原来的状态
                for (String orderStatusStr : orderStatusArray) {
                    Byte orderStatus = Byte.valueOf(orderStatusStr);
                    OrderRefundsModel orm = this.orderDAO.selectOrderRefundsById(id);
                    OrderModel orderModel = new OrderModel();
                    orderModel.setOrderStatus(orderStatus);
                    orderModel.setId(orm.getOrderId());
                    this.orderDAO.updateOrderStatus(orderModel);
                }
            }

        }
    }

    @Override
    public List<OrderModel> selectHandOverOrdersComfirmed(String orderIds) throws ServiceException {
        List<OrderModel> orderList = this.orderDAO.selectHandOverOrdersComfirmed(orderIds);
        // step3:为每个订单设置对应的订单详情列表
        Map<String, Object> map = new HashMap<String, Object>();
        for (int i = 0; i < orderList.size(); i++) {
            map.put("orderId", orderList.get(i).getId());
            map.put("goodsType", GoodsModel.GOODS_TYPE_DEFALUT);
            List<OrderDetailsModel> orderDetailList = this.orderDAO
                .selectHandOverOrderComfirmedDetails(map);
            orderList.get(i).setGoodsList(orderDetailList);
        }
        return orderList;
    }

    @Override
    public List<OrdersTodayModel> selectTodayOrders(Map<String, Object> map)
                                                                            throws ServiceException {
        return this.orderDAO.selectTodayOrders(map);
    }

    @Override
    public Long selectTodayOrdersCount(Map<String, Object> map) throws ServiceException {
        return this.orderDAO.selectTodayOrdersCount(map);
    }

}
